package util

import (
	"fmt"
	"os"
	"os/user"
	"path"
	"path/filepath"
	"strings"

	"gopkg.in/yaml.v3"

	"file_explorer/common/consts"
)

// 获取用户目录
func GetHomeDir() string {
	current, _ := user.Current()
	return current.HomeDir
}

// 获取工作目录，用于保存配置和日志文件
func GetWorkDir() string {
	current, _ := user.Current()
	workDir := PathJoin(current.HomeDir, consts.GlobalConfDirName)
	err := MkdirIfNotExist(workDir)
	if err != nil {
		return "."
	}

	return workDir
}

// 文件路径app格式转化成os格式
func FormatPath(path string) string {
	path = strings.ReplaceAll(path, "\\", "/")
	if !IsOsWindows() || path == "/" {
		return path
	}
	if path[0] == '/' {
		path = path[1:]
	}
	if path[len(path)-1] == ':' {
		path = path + "/"
	}
	return path
}

func PathJoin(paths ...string) string {
	return FormatPath(path.Join(paths...))
}

func PathSplit2Nodes(absolutePath string) []string {
	if absolutePath == "/" {
		return []string{absolutePath}
	}
	absolutePath = FormatPath(absolutePath)
	dirs := strings.Split(absolutePath, "/")
	if IsOsWindows() {
		dirs = append([]string{"/"}, dirs...)
	} else {
		dirs[0] = "/"
	}
	return dirs
}

func PathSplit(absolutePath string) (string, string) {
	dirs := PathSplit2Nodes(absolutePath)
	return PathJoin(dirs[:(len(dirs) - 1)]...), dirs[len(dirs)-1]
}

func PathExists(path string) bool {
	path = FormatPath(path)
	_, err := os.Stat(path)
	return err == nil || os.IsExist(err)
}

func PathIsDir(path string) bool {
	info, _ := os.Stat(path)
	return info != nil && info.IsDir()
}

func MkdirIfNotExist(dir string) error {
	if PathExists(dir) {
		return nil
	}
	return os.Mkdir(dir, os.ModePerm)
}

func SplitFilename(filename string) (name, extName string) {
	index := strings.Index(filename, ".")
	if index <= 0 {
		return filename, ""
	}
	return filename[:index], filename[index+1:]
}

func JoinFilename(name, extName string) string {
	if len(extName) == 0 {
		return name
	}
	return name + "." + extName
}

func AddSuffix(filename string, suffix string) string {
	name, extName := SplitFilename(filename)
	return JoinFilename(name+suffix, extName)
}

func IsSamePartition(path1, path2 string) bool {
	return filepath.VolumeName(path1) == filepath.VolumeName(path2)
}

func WriteYmlFile(data interface{}, path string) error {
	bytes, err := yaml.Marshal(data)
	if err != nil {
		return err
	}

	fp, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
	if err != nil {
		return err
	}

	_, err = fp.Write(bytes)
	if err != nil {
		return err
	}

	return nil
}

func ReadYmlFile(path string, data interface{}) error {
	bytes, err := os.ReadFile(path)
	if err != nil {
		return err
	}

	return yaml.Unmarshal(bytes, data)
}

func ResolveFilenameConflict(path string) (string, error) {
	newPath := path
	i := 1
	for PathExists(newPath) {
		newPath = AddSuffix(path, fmt.Sprintf(" (%d)", i))
		i++
		if i > 1000 {
			return "", fmt.Errorf("resolve filename conflict failed, path=%v", path)
		}
	}
	return newPath, nil
}
